/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhike
 * date:2016年5月1日
 *
 */
package com.acooly.module.openapi.client.provider.sinapay.message.trade;

import com.acooly.core.utils.Ids;
import com.acooly.core.utils.Money;
import com.acooly.core.utils.validate.jsr303.MoneyConstraint;
import com.acooly.module.openapi.client.api.anotation.ApiItem;
import com.acooly.module.openapi.client.api.enums.ApiMessageType;
import com.acooly.module.openapi.client.provider.sinapay.SinapayConstants;
import com.acooly.module.openapi.client.provider.sinapay.annotation.ApiTransient;
import com.acooly.module.openapi.client.provider.sinapay.annotation.SinaGateWay;
import com.acooly.module.openapi.client.provider.sinapay.domain.SinapayApiMsg;
import com.acooly.module.openapi.client.provider.sinapay.domain.SinapayRequest;
import com.acooly.module.openapi.client.provider.sinapay.enums.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.NotEmpty;

import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
 * 代收 请求接口
 * 
 * 注意：通过setPayMode来设置代付方式。
 * 
 * @author zhike
 */
@Getter
@Setter
@SinaGateWay(SinapayGateWayType.PAYMENT)
@SinapayApiMsg(service = SinapayServiceNameEnum.CREATE_HOSTING_COLLECT_TRADE, type = ApiMessageType.Request)
public class CreateHostingCollectTradeRequest extends SinapayRequest {

	public static final String TRADE_TYPE_FREEZE = "pre_auth";

	/**
	 * 交易订单号
	 *
	 * 商户网站交易订单号，商户内部保证唯一
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "out_trade_no")
	private String outTradeNo = Ids.oid();

	/**
	 * 交易码
	 *
	 * 商户网站代收交易业务码，见附录
	 */
	@NotEmpty
	@Size(max = 16)
	@ApiItem(value = "out_trade_code")
	private String outTradeCode = SinapayOutTradeCode.INVEST_IN.code();

	/**
	 * 摘要
	 *
	 * 交易内容摘要
	 */
	@NotEmpty
	@Size(max = 64)
	@ApiItem(value = "summary")
	private String summary = "借款投资";

	/**
	 * 交易关闭时间
	 *
	 * 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭。取值范围：1m～15d。m-分钟，h-小时，d-天不接受小数点，如1.5d，
	 * 可转换为36h。如果是代收完成交易，则该关闭时间指冻结成功前有效时间。
	 */
	@Size(max = 8)
	@ApiItem(value = "trade_close_time")
	private String tradeCloseTime;

	/**
	 * 支付失败后是否可以再次支付
	 *
	 * 支付失败后，是否可以重复发起支付。取值范围：Y、N(忽略大小写)。Y：可以再次支付；N：不能再次支付；默认值为N；如果为代收冻结交易，
	 * 则表示代收完成失败后是否可以再次发起代收完成。取值范围：Y、N(忽略大小写)；Y：代收完成失败后可以再次发起代收完成。（交易状态为代收冻结成功）；
	 * N：代收完成失败后不可以发起代收完成。（交易状态为交易失败，会自动触发代收撤销）默认值为N
	 */
	@Size(max = 1)
	@ApiItem(value = "can_repay_on_failed")
	private String canRepayOnFailed;

	/**
	 * 收银台地址类别
	 *
	 * 收银台地址类型，目前只包含MOBILE。为空时默认返回PC版页面，当传值为“MOBILE”时返回移动版页面。
	 */
	@Size(max = 10)
	@ApiItem(value = "cashdesk_addr_category")
	private String cashdeskAddrCategory;

	/**
	 * 商户标的号
	 *
	 * 对应“标的录入”接口中的标的号，用来关联此笔代收和标的
	 */
	@Size(max = 64)
	@ApiItem(value = "goods_id")
	private String goodsId;

	/**
	 * 交易关联号
	 *
	 * 商户交易关联号，用于代收代付交易关联
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "trade_related_no")
	private String tradeRelatedNo;

	/**
	 * 付款用户ID
	 *
	 * 商户系统用户ID(字母或数字)
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "payer_id")
	private String payerId;

	/**
	 * 标识类型
	 *
	 * ID的类型，参考“标志类型”
	 */
	@NotEmpty
	@Size(max = 16)
	@ApiItem(value = "payer_identity_type")
	private String payerIdentityType = "UID";

	/**
	 * 付款用户IP地址
	 *
	 * 用户在商户平台发起支付时候的IP地址，公网IP，不是内网IP，用于风控校验，请填写用户真实IP，否则容易风控拦截
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "payer_ip")
	private String payerIp;

	/**
	 * 支付方式
	 *
	 * 格式：支付方式^金额^扩展|支付方式^金额^扩展。扩展信息内容以“，”分隔，针对不同支付方式的扩展定义见附录 “支付方式扩展”
	 */
	@Size(max = 1000)
	@ApiItem(value = "pay_method")
	private String payMethod;

	@MoneyConstraint
	@Transient
	private Money amount;
	/**
	 * 新浪支付方式
	 */
	@ApiTransient
	@NotNull
	private SinapayMode payMode = SinapayMode.BALANCE;
	@ApiTransient
	private SinapayBankCode bankCode = SinapayBankCode.SINAPAY;
	@ApiTransient
	private SinapayCardType cardType = SinapayCardType.DEBIT;
	/** 卡属性 */
	@ApiTransient
	private SinapayCardAttribute cardAttribute = SinapayCardAttribute.C;
	@ApiTransient
	@NotNull
	private SinapayAccountType accountType = SinapayAccountType.SAVING_POT;

	/**
	 * 代收交易类型
	 *
	 * 1、代收冻结交易传pre_auth，其它场景不传该参数。2、代收冻结用户的账户余额；比如：用户的投资操作，商户想先冻结用户存钱的份额（代收冻结），
	 * 保证用户的存钱罐余额在冻结期间仍然享受货基收益；
	 */
	@Size(max = 32)
	@ApiItem(value = "collect_trade_type")
	private String collectTradeType;

	public CreateHostingCollectTradeRequest() {
	}

	/**
	 * @param summary
	 * @param payerId
	 * @param payerIp
	 * @param amount
	 */
	public CreateHostingCollectTradeRequest(String summary, String payerId, String payerIp, Money amount) {
		this();
		this.summary = summary;
		this.payerId = payerId;
		this.payerIp = payerIp;
		this.amount = amount;
	}

	public CreateHostingCollectTradeRequest(String summary, String payerId, Money amount, boolean freeze,
			String payerIp) {
		this();
		this.summary = summary;
		this.payerId = payerId;
		this.payerIp = payerIp;
		this.amount = amount;
		if (freeze) {
			this.collectTradeType = TRADE_TYPE_FREEZE;
		}
	}

	public String getPayMethod() {
		StringBuilder sb = new StringBuilder();
		if (payMode == SinapayMode.ONLINE_BANK) {
			setReturnUrl(SinapayConstants.GATHER_RETURN_URL);
			setExtendParam("channel_white_list^balance_svp;balance");
			sb.append(payMode.code()).append("^").append(this.amount).append("^").append(this.bankCode.code())
					.append(",").append(this.cardType.code()).append(",").append(this.cardAttribute.code());
		} else if (payMode == SinapayMode.BALANCE) {
			sb.append(payMode.code()).append("^").append(this.amount).append("^").append(this.accountType.code());
		}
		return sb.toString();
	}
}
